from django.contrib.auth import logout
from django.shortcuts import render
from django.http import HttpResponse
from utils.captcha.captcha import captcha
from apps.users.models import User
from django_redis import get_redis_connection
from django.views import View


class ImageCodeView(View):

    def get(self,request):
        # 1.接收请求
        cur = request.GET.get('cur')

        # 2.提取参数
        # captcha.generate_captcha()
        # 返回 第一个数据是 图片验证码的内容
        # 返回 第二个数据是 图片验证码的图片二进制
        text, image = captcha.generate_captcha()

        # 3.保存图片验证码 (redis)
        # 3.1 先连接redis
        from django_redis import get_redis_connection
        # get_redis_connection(配置中CACHES的名字)
        # 获取 redis 连接
        redis_cli = get_redis_connection('code')

        # 3.2 设置数据
        # setex key seconds value
        redis_cli.setex(cur, 300, text)
        # 4.返回图片响应
        # 注意事项!!!! 我们返回的不是JSON 而且 图片二进制
        # content_type='image/jpeg'
        # 告诉浏览器 哥们 我给你的二进制是图片哦 你要用图片的方式打开!!!
        return HttpResponse(image, content_type='image/jpeg')



from django.http import JsonResponse
import json
import re

class SMSCodeView(View):

    def post(self, request):
        # GET sms_codes/<mobile>/?image_code[用户输入的图片验证码]=xxxx&image_code_id[UUID 唯一标示]=xxxx
        # 1. 接收参数

        query_params = json.loads(request.body.decode())
        # 2. 提取参数
        mobile = query_params.get('mobile')
        image_code = query_params.get('text')
        image_code_id = query_params.get('id')


        # 3. 验证参数 [课上省略]
        # 3.1 验证 image_code的长度
        # 3.2 验证 imaage_code_id的 正则形式
        # 4. 比对用户输入的图片验证码和服务器的图片验证码是否一致
        # 4.1 用户输入的图片验证码

        redic_cli = get_redis_connection('code')
        redis_text = redic_cli.get(image_code_id)

        # 因为我们的图片验证码有一定的时效 获取的也可能是None
        if redis_text is None:
            return JsonResponse({'code': 400, 'errmsg': '图片验证码过期'})

        # 4.2 服务器的图片验证码.获取之后删除
        redic_cli.delete(image_code_id)

        # 4.3 比对
        if redis_text.decode().lower() != image_code.lower():
            return JsonResponse({'code': 400, 'errmsg': '图片验证码错误'})

        # 再发送前 判断 标记位是否有值 有值 说明是频繁操作
        flag = redic_cli.get('send_%s' % mobile)

        if flag:
            return JsonResponse({'code': 400, 'errmsg': '不要频繁操作'})

        # 5. 生成短信验证码
        from random import randint
        # 不满足 6位 补0
        sms_code = '%06d' % randint(0, 999999)

        # ① 创建一个管道
        pipeline = redic_cli.pipeline()

        # ② 让管道收集指令
        # 6. 保存短信验证码
        pipeline.setex(mobile, 300, sms_code)

        # 设置一个标记位.这个标记位的有效期是 60秒 标记位的值 是 任意值都可以
        pipeline.setex('send_%s' % mobile, 60, 1)

        # ③  执行管道
        pipeline.execute()

        # 7. 发送短信验证码
        from utils.sms import send_sms_code
        send_sms_code(mobile, sms_code, 5)
        # 8. 返回响应
        return JsonResponse({'code': 0})


class RegisterView(View):

    def post(self,request):

        # 1. 接收参数
        # 1.1 获取 bytes数据
        # body_bytes=request.body
        # # 1.2 bytes转str
        # body_str=body_bytes.decode()
        # # 1.3 str转字典
        # data = json.loads(body_str)

        data = json.loads(request.body.decode())

        # 2. 提取参数
        # 用户名,密码,确认密码,手机号和同意协议. 图片验证码和短信验证码 后期实现
        password=data.get('password')

        mobile=data.get('mobile')

        # 3. 验证参数 [我们不相信前端提交的任何数据]
        # 3.1 这5个参数都要有数据
        # all[变量名,变量名,...] 只要不是None或者False  就返回True
        #                       只要有一个为None,或者False 就返回False
        # 3.2 用户名需要符合规则 用户名也不能重复[不重复写了]

        # 3.3 密码符合规则
        if not re.match('[0-9A-Za-z_]{8,20}',password):
            return JsonResponse({'code':400,'errmsg':'密码不符合规则'})
        # 3.4 密码和确认密码一致
        # if password != password2:
        #     return JsonResponse({'code': 400, 'errmsg': '密码不一致'})
        # 3.5 手机号需要符合规则 手机号也不能重复[作业]
        if not re.match('1[3-9]\d{9}',mobile):
            return JsonResponse({'code': 400, 'errmsg': '手机号不符合规则'})
        # 3.6 得同意协议
        # 一会单独将

        # 4. 数据入库
        # User().save()
        # User.objects.create()
        # 以上这2种方式 都是可以的. 但是会有一个问题
        # 密码没有加密
        # 要对密码进行加密
        # Django自带的用户模型中 有对密码加密的方法
        # create_user
        user = User.objects.create_user(
            password=password,
            username=mobile,
            mobile=mobile
        )

        from django.contrib.auth import login
        # 设置状态保持
        # login(请求对象,User实例对象)
        login(request,user)

        # 5. 返回响应
        return JsonResponse({'errno':0,'errmsg':'ok'})



class LoginView(View):

    def post(self,request):
        """
        1.接收请求数据
        2.提取数据
        3.验证参数
        4.认证登录用户
        5.状态保持
        6.要根据是否记住登录(类似于 mail.163.com中的 10免登录 本质是设置session过期时间)
        7.返回响应
        :param request:
        :return:
        """
        # 1.接收请求数据
        data = json.loads(request.body.decode())
        # 2.提取数据
        mobile = data.get('mobile')
        password=data.get('password')
        # 3.验证参数
        # 用户名和密码是必须要传递的!!!

        # 3.1 用户名规格(作业)
        # 3.2 密码规格(作业)

        # 4.认证登录用户
        # django 自带 admin后台. admin 可以验证用户名和密码
        # django 实现了 用户名和密码的验证方法
        from django.contrib.auth import authenticate
        # authenticate 把用户名和密码传递过去之后,会帮助我们验证 用户名和密码是否正确
        # 如果正确,则返回 username对应的 模型对象
        # 如果不正确,则返回 None

        # 设置关键字参数
        username = mobile
        user_user = authenticate(username=username,password=password)
        user_user = authenticate(username=mobile,password=password)

        if user_user is None:
            # user is None 说明 用户名或密码不正确
            # 我们千万不要告诉 前端 准确的错误信息
            return JsonResponse({'code':400,'errmsg':'用户名或密码不正确'})
            # user 不为None　说明登录成功继续执行后续代码

        # 5.状态保持
        from django.contrib.auth import login
        login(request,user_user)


        # 6.要根据是否记住登录(类似于 mail.163.com中的 10免登录 本质是设置session过期时间)
            # remembered 用户 判断 是否勾选 记住登录状态
            # 如果勾选 ,则让 session有效期为 2周(14天)
        # request.session.set_expiry()
        # 7.返回响应

        response = JsonResponse({'errno':0,'errmsg':'登录成功'})
        response.set_cookie('mobile',user_user,max_age=14*14*36000)
        return response

    def get(self,request):
        user = request.user
        # if not user:
        #     return JsonResponse({'errno': 0, 'errmsg': '登录成功'})
        data = {
            'user_id':user.id,
            'name':user.username
        }
        return JsonResponse({'errno': 0, 'errmsg': '登录成功','data':data})


    def delete(self, request):
        logout(request)
        response = JsonResponse({'errno':0,'errmsg':'已退出'})
        response.delete_cookie('mobile')
        return response













